package com.pan.crawler.auto2.action;

import org.openqa.selenium.By;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.edge.EdgeDriver;
import org.w3c.dom.Element;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class XPathFind {

    private class MyXPath {
        private String xpath;
        private boolean isAttr;
        private String attrName;

        public MyXPath(String xpath, boolean isAttr, String attrName) {
            this.xpath = xpath;
            this.isAttr = isAttr;
            this.attrName = attrName;
        }

        public String getXpath() {
            return xpath;
        }

        public boolean isAttr() {
            return isAttr;
        }

        public String getAttrName() {
            return attrName;
        }

        public boolean elementEquals(MyXPath myXPath) {
            if (myXPath.getXpath().equals(xpath)) {
                return true;
            }
            return false;
        }

        @Override
        public String toString() {
            return "MyXPath{" +
                    "xpath='" + xpath + '\'' +
                    ", attrName='" + attrName + '\'' +
                    '}';
        }
    }

    private Map<String, MyXPath> cacheRegex;

    {
        cacheRegex = new ConcurrentHashMap<>();
    }

    public String getElementXpath(String xpathValue) {
        return parseXPath(xpathValue).getXpath();
    }

    public String getAttributeName(String xpathValue) {
        return parseXPath(xpathValue).getAttrName();
    }

    public boolean xpathElementEquals(String x1, String x2) {
        MyXPath myXPath1 = parseXPath(x1);
        MyXPath myXPath2 = parseXPath(x2);
        return myXPath2.elementEquals(myXPath1);
    }


    private MyXPath parseXPath(String xpathValue) {
        if (cacheRegex.containsKey(xpathValue)) {
            return cacheRegex.get(xpathValue);
        }
        String regex = "^([\\[\\]\\./\\w=\"\'-@\\*]+?)(?:/@([^/]+))?$";
        Pattern pattern = Pattern.compile(regex);
        String xpath;
        boolean isAttr;
        String attrName;
        Matcher matcher = pattern.matcher(xpathValue);
        if (matcher.find() && matcher.groupCount() == 2) {
            xpath = matcher.group(1);
            attrName = matcher.group(2);
        } else {
            throw new RuntimeException("xpath parse Error:" + xpathValue);
        }
        isAttr = attrName == null ? false : true;
        MyXPath myXPath = new MyXPath(xpath, isAttr, attrName);
        cacheRegex.put(xpathValue, myXPath);
        return myXPath;
    }

    public WebElement findElement(EdgeDriver edgeDriver, String xpathValue) {
        MyXPath myXPath = this.parseXPath(xpathValue);
        String xpath = myXPath.getXpath();
        for (int i = 0; i < 5; i++) {
            try {
                return edgeDriver.findElement(By.xpath(xpath));
            } catch (TimeoutException e) {
                System.out.println(e);
                try {Thread.sleep(1000);} catch (InterruptedException ex) {throw new RuntimeException(ex);}
            }
        }
        throw new RuntimeException("无法查找： xpath："+xpathValue);
    }

    //不做异常处理
    public String find(EdgeDriver edgeDriver, String xpathValue) {
        MyXPath myXPath = this.parseXPath(xpathValue);
        boolean isAttr = myXPath.isAttr();
        String attrName = myXPath.getAttrName();
        WebElement element = findElement(edgeDriver, xpathValue);
        if (element == null) {
            return null;
        }
        String result = isAttr ? element.getAttribute(attrName) : element.getText();
        return result;
    }


    public List<WebElement> findElements(EdgeDriver edgeDriver, String xpathValue) {
        MyXPath myXPath = this.parseXPath(xpathValue);
        String xpath = myXPath.getXpath();
        return edgeDriver.findElements(By.xpath(xpath));
    }

    public List<String> finds(EdgeDriver edgeDriver, String xpathValue) {
        MyXPath myXPath = this.parseXPath(xpathValue);
        boolean isAttr = myXPath.isAttr();
        String attrName = myXPath.getAttrName();
        List<WebElement> elements = findElements(edgeDriver, xpathValue);
        if (elements == null || elements.size() == 0) {
            return null;
        }
        List<String> resultList = new ArrayList<>();
        if (isAttr) {
            for (WebElement e : elements) {
                String attribute = e.getAttribute(attrName);
                resultList.add(attribute);
            }
        } else {
            for (WebElement e : elements) {
                String text = e.getText();
                resultList.add(text);
            }
        }
        return resultList;
    }

}
